﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.SqlServer.Dts.Pipeline;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using MouldingAndMillwork;

namespace MouldingAndMillwork.SSIS
{
	public partial class SSISUtility
    {
        #region SSIS Error Interpretation
        public static string GetSSISErrorMessage(IDTSComponentMetaData100 md, Exception Err)
		{
			try
			{
				COMException comEx = Err as COMException;
				string errorMessage = md.GetErrorDescription(comEx.ErrorCode);
				return errorMessage;
			}
            #region catch ...
            catch
			{
				return Err.Message;
            }
            #endregion
        }

		public static string GetSSISErrorMessage(IDTSComponentMetaData100 md, string errMsg)
		{
			try
			{
				//try and get the error code from the error message 
				int hexPos = errMsg.IndexOf("0x");
				if (hexPos >= 0 && errMsg.Length > hexPos + 2)
				{
					string errCode = errMsg.Substring(hexPos + 2, 8);
					//Debug.Print(errCode);
					int errNum = Convert.ToInt16(errCode, 16);
					return md.GetErrorDescription(errNum);
				}
				return errMsg;

			}
            #region catch ...
            catch
			{
				return errMsg;
            }
            #endregion
        }
		#endregion

        #region System Information
        public static int GetNumberOfProcessorCores()
		{
			int processorMask = System.Diagnostics.Process.GetCurrentProcess().ProcessorAffinity.ToInt32();
			int numProcessors = (int)Math.Log(processorMask, 2) + 1;
			return Math.Max(1, numProcessors);
		}
		#endregion

        #region SSIS Object Model Wrappers

		public static IDTSOutputColumn100 FindColumnByName(IDTSOutput100 output, string columnName)
		{
			IDTSOutputColumn100 foundColumn = null;

			foreach (IDTSOutputColumn100 outputColumn in output.OutputColumnCollection)
			{
				if (outputColumn.Name == columnName)
				{
					foundColumn = outputColumn;
					break;
				}
			}

			return foundColumn;
		}
		#endregion
    }

    #region CLASS: BinaryFormatter
    public class BinaryFormatter : IFormatProvider, ICustomFormatter
    {
        // IFormatProvider.GetFormat implementation.
        public object GetFormat(Type formatType)
        {
            // Determine whether custom formatting object is requested.
            if (formatType == typeof(ICustomFormatter))
                return this;
            else
                return null;
        }

        // Format number in binary (B), octal (O), or hexadecimal (H).
        public string Format(string format, object arg, IFormatProvider formatProvider)
        {
            // Handle format string.
            int baseNumber;
            // Handle null or empty format string, string with precision specifier.
            string thisFmt = String.Empty;
            // Extract first character of format string (precision specifiers
            // are not supported).
            if (!String.IsNullOrEmpty(format))
                thisFmt = format.Length > 1 ? format.Substring(0, 1) : format;

            switch (thisFmt.ToUpper())
            {
                // Binary formatting.
                case "B":
                    baseNumber = 2;
                    break;
                case "O":
                    baseNumber = 8;
                    break;
                case "H":
                    baseNumber = 16;
                    break;
                // Handle unsupported format strings.
                default:
                    if (arg is IFormattable)
                        return ((IFormattable)arg).ToString(format, formatProvider);
                    else if (arg != null)
                        return arg.ToString();
                    // arg is null.
                    else
                        return String.Empty;
            }

            // Get a byte array representing the numeric value.
            byte[] bytes;
            if (arg is sbyte)
            {
                string byteString = ((sbyte)arg).ToString("X2");
                bytes = new byte[1] { Byte.Parse(byteString, System.Globalization.NumberStyles.HexNumber) };
            }
            else if (arg is byte)
            {
                bytes = new byte[1] { (byte)arg };
            }
            else if (arg is short)
            {
                bytes = BitConverter.GetBytes((short)arg);
            }
            else if (arg is int)
            {
                bytes = BitConverter.GetBytes((int)arg);
            }
            else if (arg is long)
            {
                bytes = BitConverter.GetBytes((long)arg);
            }
            else if (arg is ushort)
            {
                bytes = BitConverter.GetBytes((ushort)arg);
            }
            else if (arg is uint)
            {
                bytes = BitConverter.GetBytes((uint)arg);
            }
            else if (arg is ulong)
            {
                bytes = BitConverter.GetBytes((ulong)arg);
            }
            else
            {
                throw new ArgumentException(String.Format("BinaryFormatter does not support the {0} value {1}.",
                                            arg.GetType().Name, arg));
            }

            // Return a formatted string.
            string numericString = String.Empty;
            for (int ctr = bytes.GetUpperBound(0); ctr >= bytes.GetLowerBound(0); ctr--)
            {
                string byteString = Convert.ToString(bytes[ctr], baseNumber);
                if (baseNumber == 2)
                    byteString = new String('0', 8 - byteString.Length) + byteString;
                else if (baseNumber == 8)
                    byteString = new String('0', 4 - byteString.Length) + byteString;
                // Base is 16.
                else
                    byteString = new String('0', 2 - byteString.Length) + byteString;

                numericString += byteString + " ";
            }
            return numericString.Trim();
        }
    }
    #endregion

    #region CLASS: PositiveOrNegative
    public class PositiveOrNegative
    {
        public enum Sign
        {
            Positive,
            Negative,
            None
        }

        public static bool IsPositive(int number)
        {
            return number > 0;
        }

        public static bool IsNegative(int number)
        {
            return number < 0;
        }

        public static Sign GetSign(int number)
        {
            if (number < 0)
            {
                return Sign.Negative;
            }
            else if (number > 0)
            {
                return Sign.Positive;
            }
            else
            {
                return Sign.None;
            }
        }
    }
    #endregion
}
